home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / util / conv / Cas2Wav.lha / Cas2Wav.c next >
Encoding:
C/C++ Source or Header  |  2002-02-18  |  69.0 KB  |  2,107 lines

  1. /*****************************************************************************
  2. **
  3. **  Copyright 1998, 1999 by Ernest R. Schreurs.
  4. **  All rights reserved.
  5. **  Use of this source code is allowed under the following conditions:
  6. **  You must inform people that you based your work on this stuff.
  7. **  If you charge a fee in any form for your product, you must inform people
  8. **  that this stuff is available free of charge.
  9. **  Refer to the documentation for more information.
  10. **
  11. *****************************************************************************/
  12. #define MODULE  "CAS2WAV.C"
  13. /*****************************************************************************
  14. **  NAME: CAS2WAV.C
  15. **
  16. **  Author            : Ernest R. Schreurs
  17. **  Date              : January 3, 1999
  18. **  Release           : 01.00
  19. **
  20. **  Description       : This program will convert a .cas cassette image file
  21. **                      to a .wav file.
  22. **
  23. **  Amiga port by Wojciech Pasiecznik (voydial@wp.pl), Feb. 14, 2002.
  24. **  Few additional changes:
  25. **
  26. ** - Control Z check is replaced by the Control C (including comments),
  27. ** - title is a little changed ;),
  28. ** - "fltenv.h" include file is disabled now.
  29. **
  30. *****************************************************************************/
  31.  
  32. /*****************************************************************************
  33. ==  INCLUDE FILES
  34. *****************************************************************************/
  35. #include <stdio.h>              /* For printf() and gets()              */
  36. #include <ctype.h>              /* For isalnum() and toupper()          */
  37. /* #include <fltenv.h>          /* For sin() exceptions                 */
  38. #include <math.h>               /* For sin()                            */
  39. #include <stdlib.h>             /* For the exit function                */
  40. #include <string.h>             /* String and memory stuff              */
  41.  
  42. /*****************************************************************************
  43. ==  DEFINED SYMBOLS
  44. *****************************************************************************/
  45.  
  46. #ifndef FALSE
  47. #define FALSE               0
  48. #endif
  49. #ifndef TRUE
  50. #define TRUE                1
  51. #endif
  52.  
  53. #ifndef NULL
  54. #define NULL                0
  55. #endif
  56. #define PATH_LEN            128             /* Maximum path length          */
  57.  
  58. #define BUF_LEN             80              /* fgets buffer length          */
  59. #define SUCCESS             1               /* Success is non-zero          */
  60. #define FAILURE             0               /* Failure is zero              */
  61. #define ZERO_LEVEL          128             /* Zero level for wav sample    */
  62.  
  63. /*
  64. **  A tape record starts with a Pre-Record Write Tone.
  65. **  Then we find bytes, usually 132, each starting with a startbit,
  66. **  eight data bits, lsb first, followed by a stopbit.
  67. **  This is all coded in mark and space tones, as defined below.
  68. */
  69. #define FSK_MARK            1               /* Mark tone represents a 1     */
  70. #define FSK_SPACE           0               /* Space tone represents a 0    */
  71. #define FSK_1               1               /* A 1 bit is a mark            */
  72. #define FSK_0               0               /* A 0 bit is a space           */
  73. #define FSK_PRWT            1               /* PRWT tone is a mark          */
  74. #define FSK_STARTBIT        0               /* Startbit is a space          */
  75. #define FSK_STOPBIT         1               /* Stopbit is a mark            */
  76.  
  77. /*
  78. **  Definitions for the mark and space tone frequencies.
  79. */
  80. #define FSK_TONE_MARK       5327            /* Frequency of mark tone       */
  81. #define FSK_TONE_SPACE      3995            /* Frequency of space tone      */
  82. #define MARK_TABLE_LEN      44100L          /* Length of mark tone table    */
  83. #define SPACE_TABLE_LEN     44100L          /* Length of space tone table   */
  84.  
  85. /*****************************************************************************
  86. ==  MACRO DEFINITIONS
  87. *****************************************************************************/
  88. /*
  89. **  Macro for casting stuff to requirements of stupid
  90. **  standard library functions.
  91. */
  92.  
  93. #define FGETS( buf, buf_len, file_ptr )                                 \
  94.     (void *)fgets( (char *)buf, (int)buf_len, (FILE *)file_ptr )
  95.  
  96. #define STRLEN( str )                                                   \
  97.     strlen( (const char *)(str) )
  98.  
  99. /*
  100. **  Macro for getting input from the terminal,
  101. **  allowing the user to exit with either control C or
  102. **  inputting the string ^C to indicate intention of
  103. **  terminating the program.
  104. */
  105. #define GET_BUF()                                                           \
  106. {                                                                           \
  107.     if ( FGETS( buf, BUF_LEN, stdin )  ==  NULL )                           \
  108.     {                                                                       \
  109.         printf( "Terminated by ^C\n" );                                     \
  110.         exit(0);                                                            \
  111.     }                                                                       \
  112.     if ( memcmp( buf, "^C", 2 ) == 0 || memcmp( buf, "^c", 2 ) == 0  )      \
  113.     {                                                                       \
  114.         printf( "Terminated by ^C\n" );                                     \
  115.         exit(0);                                                            \
  116.     }                                                                       \
  117. }
  118.  
  119. #define PRINT( lst )                                                        \
  120. {                                                                           \
  121.     if( diagnostics )                                                       \
  122.     {                                                                       \
  123.         printf lst;                                                         \
  124.     }                                                                       \
  125. }
  126.  
  127. /*****************************************************************************
  128. ==  TYPE and STRUCTURE DEFINITIONS
  129. *****************************************************************************/
  130. typedef     unsigned char   bool;   /* Boolean value                        */
  131. typedef     unsigned char   ubyte;  /* Exactly eight bits, unsigned         */
  132. typedef     short           int16;  /* At least 16 bits, signed             */
  133. typedef     unsigned short  uint16; /* At least 16 bits, unsigned           */
  134. typedef     long            int32;  /* At least 32 bits, signed             */
  135. typedef     unsigned long   uint32; /* At least 32 bits, unsigned           */
  136.  
  137. /*
  138. **  Cassette file header.
  139. */
  140.  
  141. typedef struct
  142. {
  143.     ubyte       cas_record_id[4];       /* Cassette record type             */
  144.     ubyte       cas_len_lo;             /* Record length low byte           */
  145.     ubyte       cas_len_hi;             /* Record length high byte          */
  146.     ubyte       cas_aux1;               /* Type dependant data              */
  147.     ubyte       cas_aux2;               /* Type dependant data              */
  148.     ubyte       cas_data[8192];         /* Data                             */
  149. } cas_blk;
  150.  
  151. /*****************************************************************************
  152. ==  IMPORTED VARIABLES
  153. *****************************************************************************/
  154. /*****************************************************************************
  155. ==  LOCAL ( HIDDEN ) VARIABLES
  156. *****************************************************************************/
  157. static FILE *   cas_file;               /* Cassette image file              */
  158. static FILE *   wav_file;               /* Wave file                        */
  159.  
  160. static cas_blk  cas_rec;                /* The cassette record buffer       */
  161. static uint32   cas_len;                /* Length of cassette data          */
  162.  
  163. static uint32   baudrate;               /* Baudrate                         */
  164. static bool     baudrate_fixed;         /* Fixed baudrate entered           */
  165. static uint32   bitlen;                 /* Number of samples in one bit     */
  166. static uint32   bit_stretch;            /* Number of samples for stretch    */
  167. static uint32   bytelen;                /* Number of samples in one byte    */
  168. static bool     diagnostics;            /* Print diagnostic data            */
  169. static bool     header_written;         /* Did we write out a header yet    */
  170. static bool     format_pure;            /* Format is pure sine waves        */
  171. static bool     format_sine;            /* Format is sine waves             */
  172. static bool     format_square;          /* Format is square waves           */
  173. static bool     zero_transition;        /* Do a transition at zero level    */
  174. static uint32   test_tape;              /* Generate test tape only          */
  175. static uint32   mark_tone;              /* Frequency of mark tone           */
  176. static uint32   space_tone;             /* Frequency of space tone          */
  177. static uint32   leader;                 /* Fixed length of leader           */
  178. static uint32   irg;                    /* Fixed length of Inter Record Gap */
  179. static uint32   pos;                    /* Number of bytes in wav file      */
  180. static uint32   pos_chunk_size;         /* Position in wav file for length  */
  181. static uint32   pos_file_size;          /* Position in wav file for length  */
  182. static ubyte    number[4];              /* Buffer for numbers               */
  183. static ubyte *  mark;                   /* Buffer with mark tone generator  */
  184. static ubyte *  space;                  /* Buffer with space tone generator */
  185. static ubyte *  ptr;                    /* Pointer to tone generator        */
  186. static uint32   table_len;              /* Length of generator table        */
  187. static uint32   prev_bitvalue;          /* Last bit value written           */
  188. static uint32   recno;                  /* Record number                    */
  189.  
  190. /*****************************************************************************
  191. ==  EXPORTED VARIABLES
  192. *****************************************************************************/
  193. /*****************************************************************************
  194. ==  IMPORTED FUNCTIONS
  195. *****************************************************************************/
  196. /*****************************************************************************
  197. ==  LOCAL ( HIDDEN ) FUNCTIONS
  198. *****************************************************************************/
  199. static void     cleanup( void );
  200. static uint32   process_header( void );
  201. static void     process_record( void );
  202. static uint32   read_record( void );
  203. static void     usage( char * cmd );
  204. static void     write_wav( char * buffer, uint32 buflen );
  205. static void     write_wav_bit( uint32 value, uint32 samples );
  206. static void     write_wav_number( uint32 value, uint32 buflen );
  207.  
  208. /*****************************************************************************
  209. ==  EXPORTED FUNCTIONS
  210. *****************************************************************************/
  211. int                 main();                 /* Normal entry point to it all */
  212.  
  213. /*****************************************************************************
  214. ==  LOCAL ( HIDDEN ) FUNCTIONS
  215. *****************************************************************************/
  216.  
  217. /*****************************************************************************
  218. **  NAME:  cleanup()
  219. **
  220. **  PURPOSE:
  221. **      Cleanup any mess that was created.
  222. **
  223. **  DESCRIPTION:
  224. **      This function will attempt to close all open files and
  225. **      free allocated memory.
  226. **
  227. **  INPUT:
  228. **      - The file pointers and paths are used.
  229. **
  230. **  OUTPUT:
  231. **      The function returns nothing.
  232. **
  233. */
  234.  
  235. static void         cleanup( void )
  236. {
  237.     if( wav_file )
  238.     {
  239.         fclose( wav_file );
  240.     }
  241.     if( cas_file )
  242.     {
  243.         fclose( cas_file );
  244.     }
  245.  
  246.     if( mark )
  247.         free( (void *)mark );
  248.  
  249.     if( space )
  250.         free( (void *)space );
  251.     return;
  252. }
  253.  
  254. /*****************************************************************************
  255. **  NAME:  process_header()
  256. **
  257. **  PURPOSE:
  258. **      Process the data from the header of the .cas file and store
  259. **      relevant information.  This will verify that the file truly is
  260. **      a cassette image file.
  261. **
  262. **  DESCRIPTION:
  263. **      This function will read the relevant data about the .cas file
  264. **      and verify it.
  265. **
  266. **  INPUT:
  267. **      Nothing.
  268. **      Data is read from the cassette image file.
  269. **
  270. **  OUTPUT:
  271. **      Prints results.
  272. **      Stores data related to the contents of the cassette image file.
  273. **      Returns SUCCESS if header was processed successfully.
  274. **      Returns FAILURE if some error occurred.
  275. **
  276. */
  277.  
  278. static uint32       process_header( void )
  279. {
  280.     uint32          bytes;                  /* Number of bytes read         */
  281.  
  282. /*
  283. **  Cassette image files usually look like this
  284. **
  285. **  char[4] = "FUJI", two chars record size lo/hi, two chars null
  286. **  char[4] = "baud", two chars null, two chars baudrate lo/hi
  287. **  char[4] = "data", two chars record size lo/hi, two chars PRWT lo/hi
  288. **  See below for more details.
  289. */
  290.  
  291. /*
  292. **  .cas files should begin with FUJI, followed by the size of the description.
  293. */
  294.     bytes = fread( (char *)&cas_rec, (int)1, (int)4, cas_file );
  295.     if( ( bytes < 4 ) || memcmp( cas_rec.cas_record_id, "FUJI", 4 ) )
  296.     {
  297.         fprintf(stderr, "\nThis is not a valid .cas file, it does not begin with \"FUJI\".\n");
  298.         return( FAILURE );
  299.     }
  300.  
  301. /*
  302. **  Get the remaining four bytes of the record header.
  303. */
  304.     bytes = fread( ((char *)&cas_rec)+4, (int)1, (int)4, cas_file );
  305.     if( bytes < 4 )
  306.     {
  307.         fprintf(stderr, "\nThis is not a valid .cas file, description length missing.\n");
  308.         return( FAILURE );
  309.     }
  310.  
  311. /*
  312. **  This looks like what we wanted, so we will call this success.
  313. **  Position the file at the beginning again.
  314. */
  315.     fseek( cas_file, 0L, SEEK_SET );    /* Go back to beginning of file */
  316.     return( SUCCESS );
  317. }
  318.  
  319. /*****************************************************************************
  320. **  NAME:  process_record()
  321. **
  322. **  PURPOSE:
  323. **      There is data in the cassette record buffer.  This must now be
  324. **      converted to the selected format.
  325. **
  326. **  DESCRIPTION:
  327. **      This function will take data from the record buffer and convert it
  328. **      to FSK bits.  The bits are coded as mark and space tones.
  329. **      These tones are output as wave data.
  330. **
  331. **  INPUT:
  332. **      Nothing.
  333. **      Data is taken from the cassette record buffer.
  334. **
  335. **  OUTPUT:
  336. **      Data is output to the file.
  337. **      The function returns nothing.
  338. **
  339. */
  340.  
  341. static void         process_record( void )
  342. {
  343.     uint32          bit;                    /* Number of bits processed     */
  344.     uint32          bitvalue;               /* Current bit level counting   */
  345.     ubyte           byte;                   /* Byte decoded from fsk data   */
  346.     uint32          bytes;                  /* Number of bytes read         */
  347.     uint32          change;                 /* Bit change index             */
  348.     uint32          changes;                /* Bit changes index            */
  349. /*  uint32          msecs;                  /* Number of milli-seconds      */
  350.     uint32          prwt;                   /* Length of the PRWT           */
  351.     uint32          bits[10];               /* Number of bits               */
  352.     uint32          remainder;              /* Left over samples            */
  353.     uint32          samples[10];            /* Number of samples per bit    */
  354.     uint32          total;                  /* Total sample count           */
  355.     uint32          total_bits;             /* Total number of bits         */
  356.  
  357. /*
  358. **  Currently, we only have three types of record:
  359. **  FUJI  A header/description record.
  360. **  baud  A record telling us the baudrate.
  361. **  data  A record with cassette data.
  362. */
  363.  
  364. /*
  365. **  If we find a header, and it is the first one, write the header
  366. **  for the wave file.
  367. */
  368.     if( memcmp( cas_rec.cas_record_id, "FUJI", 4 ) == 0 )
  369.     {
  370.         PRINT( ("\nDescription \"%.*s\".\n", (int)cas_len, cas_rec.cas_data) );
  371.         if( !header_written )
  372.         {
  373.             write_wav( (char *)"RIFF", (uint32)4L );
  374.             pos_file_size = pos;
  375.             write_wav_number( (uint32)0L, (uint32)4L );
  376.             header_written = TRUE;
  377.         }
  378.         write_wav( (char *)"WAVE", (uint32)4L );
  379.  
  380.         write_wav( (char *)"fmt ", (uint32)4L );
  381.         write_wav_number( (uint32)16L, (uint32)4L ); /* Header size */
  382.  
  383.         write_wav_number( (uint32)1L, (uint32)2L );  /* fmt tag 1 */
  384.         write_wav_number( (uint32)1L, (uint32)2L );  /* channels 1 */
  385.         write_wav_number( (uint32)44100L, (uint32)4L );  /* sample rate 44100 */
  386.         write_wav_number( (uint32)44100L, (uint32)4L );  /* Bytes per second */
  387.         write_wav_number( (uint32)1L, (uint32)2L );  /* Buffer alignment */
  388.  
  389.         write_wav_number( (uint32)8L, (uint32)2L );  /* bits per sample */
  390.  
  391.         write_wav( (char *)"data", (uint32)4L );
  392.         pos_chunk_size = pos;
  393.         write_wav_number( (uint32)0L, (uint32)4L );
  394.  
  395.         return;
  396.     }
  397.  
  398. /*
  399. **  If this is a baudrate record, change the baud rate, unless
  400. **  the user selected a fixed baudrate.
  401. */
  402.     if( memcmp( cas_rec.cas_record_id, "baud", 4 ) == 0 )
  403.     {
  404.         if( !baudrate_fixed )
  405.         {
  406.             baudrate = (((uint32)cas_rec.cas_aux2) << 8 ) + cas_rec.cas_aux1;
  407.             bytelen = ( 44100L * 10 ) / baudrate;
  408.             bitlen = 44100L / baudrate;
  409.         }
  410.         PRINT( ("\nBaudrate set to %lu.\n", baudrate) );
  411.         return;
  412.     }
  413.  
  414. /*
  415. **  If this is a plain old data record, encode the bits.
  416. */
  417.     if( memcmp( cas_rec.cas_record_id, "data", 4 ) == 0 )
  418.     {
  419.         prwt = (((uint32)cas_rec.cas_aux2) << 8 ) + cas_rec.cas_aux1;
  420.  
  421. /*
  422. **  If there is a fixed leader, and we did not write a leader yet,
  423. **  set the length of the leader.
  424. **  If this is a normal irg or other gap, any gap less than 3 seconds
  425. **  is considered an irg and if specified, the fixed irg is used.
  426. */
  427.         if( leader )
  428.         {
  429.             prwt = leader;
  430.             leader = 0;
  431.         }
  432.         else
  433.         {
  434.             if( irg )
  435.             {
  436.                 if( prwt < 3000 )
  437.                     prwt = irg;
  438.             }
  439.         }
  440.  
  441. /*
  442. **  Each record starts out with the PRWT.
  443. **  Then we write out all the bytes in the cassette record.
  444. **  The PRWT is measured in milli-seconds.  At a sample rate of
  445. **  44,100, this means the number of samples is 44.1 times the prwt value.
  446. */
  447.         write_wav_bit( FSK_PRWT, prwt * 44 + prwt / 10 );
  448.         recno++;
  449.         PRINT( ("\nRecord %lu at offset %lu PRWT = %lu with %lu data bytes.",
  450.                  recno, pos - pos_chunk_size - 4, prwt, cas_len ) );
  451.  
  452. /*
  453. **  Now process the data record byte by byte.
  454. */
  455.         for( bytes = 0; bytes < cas_len; bytes++ )
  456.         {
  457.  
  458. /*
  459. **  Since this is FSK, we accumulate the sample counts of the bits that
  460. **  are the same value.  This way, we can get a more precise baudrate.
  461. **  Encode and sum up like bits.  Begin with a startbit, then the databits,
  462. **  and finally the stopbit.
  463. **  We need ten bits to encode one byte (startbit and stopbit included)
  464. **  but since we are using integers here, we will divide the bytelength
  465. **  by ten after summing up the bits, for improved accuracy.
  466. */
  467.             bitvalue = FSK_STARTBIT;
  468.             samples[0] = bytelen;
  469.             bits[0] = 1;
  470.             changes = 0;
  471.             byte = cas_rec.cas_data[bytes];
  472.  
  473. /*
  474. **  Convert each byte to a string of 8 bits.
  475. **  Least significant bit is encoded first.
  476. **  If the bitvalue changes, start the new count,
  477. **  otherwise add the length of a bit to the sum.
  478. */
  479.             for( bit = 0; bit < 8; bit++ )
  480.             {
  481.                 if( ( byte & 0x01 ) != bitvalue )
  482.                 {
  483.                     bitvalue = byte & 0x01;
  484.                     changes++;
  485.                     samples[changes] = bytelen;
  486.                     bits[changes] = 1;
  487.                 }
  488.                 else
  489.                 {
  490.                     samples[changes] += bytelen;
  491.                     bits[changes]++;
  492.                 }
  493.                 byte = byte >> 1;
  494.             }
  495.  
  496. /*
  497. **  The last bit is the stop bit.  Add it to the length of the last bit(s)
  498. **  if they were mark, otherwise, make a final new count.
  499. */
  500.             if( bitvalue == FSK_STOPBIT )
  501.             {
  502.                 samples[changes] += bytelen;
  503.                 bits[changes]++;
  504.             }
  505.             else
  506.             {
  507.                 changes++;
  508.                 samples[changes] = bytelen;
  509.                 bits[changes] = 1;
  510.             }
  511.  
  512. /*
  513. **  Now that we have the bits encoded, we must still divide the bytelength
  514. **  by ten, thus we must divide our sums by ten.  We must make sure that
  515. **  the baudrate is correct, so the total sum of the samples for all bits
  516. **  must be equal to the bytelength.  Distribute the remaining samples,
  517. **  caused by inaccuracy in the division, by checking the sum at every change.
  518. **  Keep a running total, and compute where we should be at, in order
  519. **  to compensate for truncation that occurs during the division.
  520. */
  521.             total = 0;
  522.             total_bits = 0;
  523.             for( change = 0; change <= changes; change++ )
  524.             {
  525.                 samples[change] /= 10;
  526.                 total += samples[change];
  527.                 total_bits += bits[change];
  528.                 remainder = (( total_bits * bytelen ) / 10 ) - total;
  529.                 samples[change] += remainder;
  530.                 total += remainder;
  531.             }
  532.  
  533. /*
  534. **  Now that we have the bits encoded, stretch the space bits.
  535. **  The table starts with the startbit, which is a space.  Steal the
  536. **  samples from the following mark bit(s).
  537. **  Even table entries are space, odd entries are mark, since they alternate.
  538. */
  539.             for( change = 0; change < changes; change++ )
  540.             {
  541.                 samples[change++] += bit_stretch;
  542.                 samples[change] -= bit_stretch;
  543.             }
  544.  
  545. /*
  546. **  Now output this stuff.
  547. **  There are at least two changes, since we have a start bit and
  548. **  a stop bit.  The bits may alternate several times, but we are
  549. **  certain that the last one will be a stop bit, which is a mark.
  550. **  Thus, process bits in pairs, alternating between space and mark.
  551. */
  552.             for( change = 0; change < changes; change++ )
  553.             {
  554.                 write_wav_bit( FSK_SPACE, samples[change++] );
  555.                 write_wav_bit( FSK_MARK, samples[change] );
  556.             }
  557.         }
  558.         return;
  559.     }
  560.  
  561.     PRINT( ("\nIn process_record() unknown record type %.4s %lu bytes data\n", &cas_rec, cas_len) );
  562.     return;
  563. }
  564.  
  565. /*****************************************************************************
  566. **  NAME:  read_record()
  567. **
  568. **  PURPOSE:
  569. **      Read a record into the cassette buffer.
  570. **
  571. **  DESCRIPTION:
  572. **      This function will read data from the cas file and store it in the
  573. **      cassette buffer.  One complete record is read into the buffer.
  574. **
  575. **  INPUT:
  576. **      Nothing.
  577. **      Data is read from the cas file.
  578. **
  579. **  OUTPUT:
  580. **      Data is stored in the buffer.
  581. **      Buffer status is updated.
  582. **      Returns SUCCESS if a record was read successfully.
  583. **      Returns FAILURE if some error occurred.
  584. **
  585. */
  586.  
  587. static uint32       read_record( void )
  588. {
  589.     uint32          bytes;                  /* Number of bytes read         */
  590.  
  591. /*
  592. **  First read the header bytes, because we need to know the length of the
  593. **  record.  If we cannot read any bytes, this must be the end of file.
  594. */
  595.     bytes = fread( (char *)&cas_rec, (int)1, (int)8, cas_file );
  596.     if( bytes == 0 )
  597.         return( FAILURE );
  598.  
  599. /*
  600. **  Found header bytes, compute the record length from the header info.
  601. **  Then read the data portion of the record, if any.
  602. */
  603.     if( bytes != 8 )
  604.     {
  605.         fprintf(stderr, "\nThis is not a valid .cas file, record header damaged.\n");
  606.         return( FAILURE );
  607.     }
  608.     cas_len = (((uint32)cas_rec.cas_len_hi) << 8 ) + cas_rec.cas_len_lo;
  609.     if( cas_len )
  610.     {
  611.         bytes = fread( (char *)cas_rec.cas_data, (int)1, (int)cas_len, cas_file );
  612.         if( bytes != cas_len )
  613.         {
  614.             fprintf(stderr, "\nThis is not a valid .cas file, record damaged.\n");
  615.             return( FAILURE );
  616.         }
  617.     }
  618.     return( SUCCESS );
  619. }
  620.  
  621. /*****************************************************************************
  622. **  NAME:  usage()
  623. **
  624. **  PURPOSE:
  625. **      Display the command line format for the program.
  626. **
  627. **  DESCRIPTION:
  628. **      This function will explain the usage of the program to the user.
  629. **      The program name is taken from the first command line argument.
  630. **
  631. **  INPUT:
  632. **      - The address of the command line, containing the program name.
  633. **
  634. **  OUTPUT:
  635. **      The usage is displayed on the terminal.
  636. **      The function returns nothing.
  637. **
  638. */
  639.  
  640. static void         usage( cmd )
  641. char * cmd;                         /* Program name                     */
  642. {
  643.     char * whoami;      /* For searching program name in command line   */
  644.     char * name;        /* Pointer to actual program name in command    */
  645.     int    len;         /* Length of program name                       */
  646.     int    found_dot;   /* Nonzero if we found a dot in the name        */
  647.  
  648. /*
  649. **  Get program name and print usage message.
  650. **  The complete pathname including extension is part of the first
  651. **  argument as passed by the operating system.
  652. */
  653.     for( whoami = cmd, len = 0, found_dot = 0; *whoami; whoami++ )
  654.     {
  655.         if( *whoami == '.' )
  656.         {
  657.             found_dot = 1;
  658.             continue;
  659.         }
  660.         if( *whoami == '\\' )   /* if this was part of the path, */
  661.         {
  662.             name = whoami + 1;  /* record position */
  663.             len = 0;            /* then restart counting length */
  664.             found_dot = 0;
  665.             continue;
  666.         }
  667.         if( *whoami == ' ' )    /* end of name found            */
  668.             break;
  669.         if( found_dot )         /* skip .exe or .com stuff      */
  670.             continue;
  671.         len++;                  /* Increment program name length */
  672.     }
  673.  
  674. /*
  675. **  Let me explain...
  676. */
  677.     fprintf(stderr, "\nUsage: %.*s [cassette file] [/d] [/w=x] [/t=nnnn] [/m=nnnn] [/s=nnnn]\n", len, name );
  678.     fprintf(stderr, "                               [/b=nnnn] [/l=nnnn] [/i=nnnn]\n");
  679.     fprintf(stderr, "to convert a .cas cassette image file to a .wav file.\n\n");
  680.     fprintf(stderr, "cassette file an Atari classic tape image file.\n");
  681.     fprintf(stderr, "/d            to print diagnostic information.\n");
  682.     fprintf(stderr, "/w=x          to select the waveform of the tone used,\n");
  683.     fprintf(stderr, "              where x is s for sine waves, b for block waves, p for pure tones.\n");
  684.     fprintf(stderr, "/z            to select transition at zero level.\n");
  685.     fprintf(stderr, "/t=nnnn       to generate a test tape only,\n");
  686.     fprintf(stderr, "              where nnnn is the duration in milli-seconds.\n");
  687.     fprintf(stderr, "/m=nnnn       frequency of mark tone in Hertz,\n");
  688.     fprintf(stderr, "              where nnnn is a number around 5327.\n");
  689.     fprintf(stderr, "/s=nnnn       frequency of space tone in Hertz,\n");
  690.     fprintf(stderr, "              where nnnn is a number around 3995.\n");
  691.     fprintf(stderr, "/b=nnnn       fixed baudrate to use,\n");
  692.     fprintf(stderr, "              where nnnn is a number around 600, from 425 to 875.\n");
  693.     fprintf(stderr, "/l=nnnn       fixed length of leader in milli-seconds,\n");
  694.     fprintf(stderr, "              where nnnn is a number around 20000.\n");
  695.     fprintf(stderr, "/i=nnnn       fixed length of Inter Record Gap in milli-seconds,\n");
  696.     fprintf(stderr, "              where nnnn is a number around 250.\n");
  697.     fprintf(stderr, "Refer to the documentation for more information.\n");
  698.  
  699.     return;
  700. }
  701.  
  702. /*****************************************************************************
  703. **  NAME:  write_test_tape()
  704. **
  705. **  PURPOSE:
  706. **      Write data for a test tape to the wav file.
  707. **
  708. **  DESCRIPTION:
  709. **      This function will write test data to the wav file.
  710. **      A test tape consists of only mark and space bits in some test pattern.
  711. **      Use an oscilloscope to view the output of the cassette unit.
  712. **
  713. **  INPUT:
  714. **      - The file pointers and paths are used.
  715. **
  716. **  OUTPUT:
  717. **      The data is written to the wav file.
  718. **      The function returns nothing.
  719. **
  720. */
  721.  
  722. static void         write_test_tape( void )
  723. {
  724.     uint32          sample_count;           /* Count of samples test tape   */
  725.     uint32          samples;                /* Number of samples test tape  */
  726.  
  727. /*
  728. **  We use a fixed filename for test tapes.
  729. */
  730.     fprintf(stderr, "\nProcessing test tape, please wait!\n");
  731.     wav_file = fopen( (char *)"testtape.wav", "wb" );
  732.     if( wav_file == NULL )
  733.     {
  734.         fprintf(stderr, "\nCannot open testtape.wav file!\n");
  735.         cleanup();
  736.         exit( 255 );
  737.     }
  738.  
  739.     if( !header_written )
  740.     {
  741.         write_wav( (char *)"RIFF", (uint32)4L );
  742.         pos_file_size = pos;
  743.         write_wav_number( (uint32)0L, (uint32)4L );
  744.         header_written = TRUE;
  745.     }
  746.     write_wav( (char *)"WAVE", (uint32)4L );
  747.  
  748.     write_wav( (char *)"fmt ", (uint32)4L );
  749.     write_wav_number( (uint32)16L, (uint32)4L ); /* Header size */
  750.  
  751.     write_wav_number( (uint32)1L, (uint32)2L );  /* fmt tag 1 */
  752.     write_wav_number( (uint32)1L, (uint32)2L );  /* channels 1 */
  753.     write_wav_number( (uint32)44100L, (uint32)4L );  /* sample rate 44100 */
  754.     write_wav_number( (uint32)44100L, (uint32)4L );  /* Bytes per second */
  755.     write_wav_number( (uint32)1L, (uint32)2L );  /* Buffer alignment */
  756.  
  757.     write_wav_number( (uint32)8L, (uint32)2L );  /* bits per sample */
  758.  
  759.     write_wav( (char *)"data", (uint32)4L );
  760.     pos_chunk_size = pos;
  761.     write_wav_number( (uint32)0L, (uint32)4L );
  762.  
  763. /*
  764. **  Compute the number of samples to generate.
  765. **  Multiply the number of milli-seconds by the sample rate.
  766. **  The sample rate is per second, so divide by 1000.
  767. */
  768.     samples = ( test_tape * 441 ) / 10;
  769.     sample_count = 0;
  770.  
  771. /*
  772. **  Generate the test pattern.
  773. */
  774.     while( sample_count < samples )
  775.     {
  776.  
  777. /*
  778. **  Alternate mark and space bits.
  779. */
  780. #if 0
  781.         write_wav_bit( FSK_MARK, bitlen );
  782.         sample_count += bitlen;
  783.         write_wav_bit( FSK_SPACE, bitlen );
  784.         sample_count += bitlen;
  785. #endif
  786.  
  787. /*
  788. **  A small piece of silence.
  789. */
  790. #if 0
  791.         for( byte = 0; byte < 881; byte++ )
  792.         {
  793.             write_wav( "\200", 1L );
  794.             sample_count++;
  795.         }
  796. #endif
  797.  
  798. /*
  799. **  Large piece of mark, and alternating space and mark,
  800. **  with elongated space bits.
  801. */
  802. #if 0
  803.         write_wav_bit( FSK_MARK, bitlen * 3 );
  804.         sample_count += bitlen * 3;
  805.         ptr = mark;
  806.         write_wav_bit( FSK_MARK, bitlen * 3 );
  807.         sample_count += bitlen * 3;
  808.         ptr = mark;
  809.         write_wav_bit( FSK_SPACE, bitlen );
  810.         sample_count += bitlen;
  811.         ptr = mark;
  812.         write_wav_bit( FSK_MARK, bitlen - 8);
  813.         sample_count += bitlen;
  814.         ptr = mark;
  815.         write_wav_bit( FSK_SPACE, bitlen + 8);
  816.         sample_count += bitlen;
  817.         ptr = mark;
  818.         write_wav_bit( FSK_MARK, bitlen - 8);
  819.         sample_count += bitlen;
  820.         ptr = mark;
  821.         write_wav_bit( FSK_SPACE, bitlen + 8);
  822.         sample_count += bitlen;
  823.         ptr = mark;
  824.         write_wav_bit( FSK_MARK, bitlen - 8);
  825.         sample_count += bitlen;
  826. #endif
  827.  
  828. /*
  829. **  Large piece of mark, and alternating space and mark,
  830. **  with abrupt change over.
  831. */
  832. #if 0
  833.         ptr = mark;
  834.         write_wav( (char *)&(mark[0]), 414 );
  835.         sample_count += 414;
  836.         write_wav( (char *)&(space[414]), 73 );
  837.         sample_count += 73;
  838.         write_wav( (char *)&(mark[487]), 73 );
  839.         sample_count += 73;
  840.         write_wav( (char *)&(space[560]), 73 );
  841.         sample_count += 73;
  842.         write_wav( (char *)&(mark[633]), 73 );
  843.         sample_count += 73;
  844.         write_wav( (char *)&(space[706]), 73 );
  845.         sample_count += 73;
  846.         write_wav( (char *)&(mark[779]), 73 );
  847.         sample_count += 73;
  848. #endif
  849.  
  850. /*
  851. **  Large piece of mark, and alternating space and mark,
  852. **  with normal change over.
  853. */
  854. #if 1
  855.         ptr = mark;
  856.         table_len = MARK_TABLE_LEN;
  857.         write_wav_bit( FSK_MARK, bitlen * 3 );
  858.         sample_count += bitlen * 3;
  859.         write_wav_bit( FSK_MARK, bitlen * 3 );
  860.         sample_count += bitlen * 3;
  861.         write_wav_bit( FSK_SPACE, bitlen );
  862.         sample_count += bitlen;
  863.         write_wav_bit( FSK_MARK, bitlen );
  864.         sample_count += bitlen;
  865.         write_wav_bit( FSK_SPACE, bitlen );
  866.         sample_count += bitlen;
  867.         write_wav_bit( FSK_MARK, bitlen );
  868.         sample_count += bitlen;
  869.         write_wav_bit( FSK_SPACE, bitlen );
  870.         sample_count += bitlen;
  871.         write_wav_bit( FSK_MARK, bitlen );
  872.         sample_count += bitlen;
  873. #endif
  874.  
  875. /*
  876. **  Large piece of mark, and alternating space and mark,
  877. **  with normal change over and elongated space bits.
  878. */
  879. #if 0
  880.         ptr = mark;
  881.         table_len = MARK_TABLE_LEN;
  882.         write_wav_bit( FSK_MARK, bitlen * 3 );
  883.         sample_count += bitlen * 3;
  884.         write_wav_bit( FSK_MARK, bitlen * 3 );
  885.         sample_count += bitlen * 3;
  886.         write_wav_bit( FSK_SPACE, bitlen + 9 );
  887.         sample_count += bitlen + 9;
  888.         write_wav_bit( FSK_MARK, bitlen - 9);
  889.         sample_count += bitlen - 9;
  890.         write_wav_bit( FSK_SPACE, bitlen + 9);
  891.         sample_count += bitlen + 9;
  892.         write_wav_bit( FSK_MARK, bitlen - 9);
  893.         sample_count += bitlen - 9;
  894.         write_wav_bit( FSK_SPACE, bitlen + 9);
  895.         sample_count += bitlen + 9;
  896.         write_wav_bit( FSK_MARK, bitlen );
  897.         sample_count += bitlen;
  898. #endif
  899.     }
  900.  
  901.     return;
  902. }
  903.  
  904. /*****************************************************************************
  905. **  NAME:  write_wav()
  906. **
  907. **  PURPOSE:
  908. **      Write data to the wav file.
  909. **
  910. **  DESCRIPTION:
  911. **      This function will write the specified buffer to the wav file.
  912. **
  913. **  INPUT:
  914. **      - The address of the data to be written.
  915. **      - The amount of data to be written.
  916. **
  917. **  OUTPUT:
  918. **      The data is written to the wav file.
  919. **      The function returns nothing.
  920. **
  921. */
  922.  
  923. static void         write_wav( buffer, buflen )
  924. char * buffer;                      /* Address of buffer to be written  */
  925. uint32 buflen;                      /* Number of bytes to be written    */
  926. {
  927.     uint32 bytes;       /* Number of bytes actually written             */
  928.  
  929.     bytes = fwrite( buffer, (int)1, (int)buflen, wav_file );
  930.     if( bytes != buflen )
  931.     {
  932.         fprintf(stderr, "\nWrite error on wav file.\n");
  933.         cleanup();
  934.         exit( 255 );
  935.     }
  936.     pos += bytes;
  937.     return;
  938. }
  939.  
  940. /*****************************************************************************
  941. **  NAME:  write_wav_bit()
  942. **
  943. **  PURPOSE:
  944. **      Write a bit or a prwt to the wav file.
  945. **
  946. **  DESCRIPTION:
  947. **      This function will write the specified number of samples to the wav
  948. **      file, representing the selected bit value.
  949. **      The way we make the transition from mark to space or from space to
  950. **      mark depends on the selected format of the waves.
  951. **
  952. **  INPUT:
  953. **      - The bit value to be represented.
  954. **      - The amount of data to be written.
  955. **
  956. **  OUTPUT:
  957. **      The data is written to the wav file.
  958. **      The function returns nothing.
  959. **
  960. */
  961.  
  962. static void         write_wav_bit( bitvalue, samples )
  963. uint32 bitvalue;                    /* The bit value to be represented  */
  964. uint32 samples;                     /* Number of bytes to be written    */
  965. {
  966.     uint32 bytes;                   /* Number of bytes actually written */
  967.     bool   falling;                 /* Level of signal is falling       */
  968.     ubyte  last_value;              /* Last byte value output           */
  969.  
  970. /*
  971. **  Here is where we have to do special things in order to make the
  972. **  selected type of transition from mark to space or from space to mark,
  973. **  if we have a transition at all.  If there is no transition, things
  974. **  are really simple.  If there is a transition, the transition from
  975. **  mark to space is the most important.  Unless we are writing pure
  976. **  tones, the mark tone is always written from the end of the mark table,
  977. **  and the space tone is written from the start of the space table.
  978. **  Unfortunately, sometimes we write a very long mark tone, which is longer
  979. **  than the table.  In this case we will be wrapping around to the start of
  980. **  the table one or more times, so compute where to start at, such that we
  981. **  we arrive at the end of the mark table.
  982. **  With pure tones, we always make a smooth transition.
  983. */
  984.  
  985. /*
  986. **  No bytes written yet.
  987. */
  988.     bytes = 0;
  989.  
  990. /*
  991. **  If only the result counts, we do not care whether or not the wave format
  992. **  looks nice, we just want it to load reliable.  For mark tones, write the
  993. **  tone from the end of the table.  For space tones, write it from the start
  994. **  of the table.  This makes the mark to space transition occur at the zero
  995. **  level.
  996. */
  997.     if( zero_transition )
  998.     {
  999.         if( bitvalue == FSK_MARK )
  1000.         {
  1001.             if( samples < MARK_TABLE_LEN )
  1002.             {
  1003.                 ptr = &(mark[MARK_TABLE_LEN - samples]);
  1004.                 table_len = samples;
  1005.             }
  1006.             else
  1007.             {
  1008.                 ptr = &(mark[MARK_TABLE_LEN - (samples % MARK_TABLE_LEN)]);
  1009.                 table_len = samples % MARK_TABLE_LEN;
  1010.             }
  1011.         }
  1012.         else
  1013.         {
  1014.             ptr = space;
  1015.             table_len = SPACE_TABLE_LEN;
  1016.         }
  1017.     } /* end if zero transition */
  1018.     else
  1019.  
  1020. /*
  1021. **  If we are writing pure tones, we must orderly end the current tone
  1022. **  before changing over to the next.
  1023. **  Complete the half period in progress before changing the tone.
  1024. */
  1025.     if( format_pure )
  1026.     {
  1027.  
  1028. /*
  1029. **  When we pass the zero level, change the tone.
  1030. **  Try to make a clean transition from mark to space.
  1031. **  Finish up the last half period of the previous bit.
  1032. **  If the bit is the same, continue with the current tone where we
  1033. **  left off.
  1034. */
  1035.         if( bitvalue != prev_bitvalue )
  1036.         {
  1037.  
  1038. /*
  1039. **  If we are at the start of our generator buffer, no need to do
  1040. **  complicated things, we can simply change to the start of the other
  1041. **  generator tone buffer.
  1042. **  Besides, we would not have a previous value in this case to determine
  1043. **  rising or falling, although we know it is rising.
  1044. */
  1045.             if( ( prev_bitvalue == FSK_MARK ) && ( ptr == mark ) )
  1046.             {
  1047.                 ptr = space;
  1048.                 table_len = SPACE_TABLE_LEN;
  1049.             }
  1050.             else
  1051.             if( ( prev_bitvalue == FSK_SPACE ) && ( ptr == space ) )
  1052.             {
  1053.                 ptr = mark;
  1054.                 table_len = MARK_TABLE_LEN;
  1055.             }
  1056.             else
  1057.  
  1058. /*
  1059. **  Otherwise, figure out whether the signal was rising or falling.
  1060. **  If we just crossed the zero level, we can see whether we are rising
  1061. **  or falling.  If the current value is below the zero level, we are now
  1062. **  falling.  If it is above the zero level, we are now rising.
  1063. */
  1064.             {
  1065.                 if( ( *(ptr - 1) >= ZERO_LEVEL ) && ( *ptr <= ZERO_LEVEL ) )
  1066.                 {
  1067.                     falling = TRUE;
  1068.                 }
  1069.                 else
  1070.                 if( ( *(ptr - 1) <= ZERO_LEVEL ) && ( *ptr >= ZERO_LEVEL ) )
  1071.                 {
  1072.                     falling = FALSE;
  1073.                 }
  1074.                 else
  1075.  
  1076. /*
  1077. **  Since we did not cross the zero level just now, look at the last value.
  1078. **  If it is above the zero level, continue to write samples until we pass
  1079. **  the zero level falling down, otherwise continue to write samples until
  1080. **  we pass the zero level going up.
  1081. */
  1082.                 if( *(ptr - 1) > ZERO_LEVEL )
  1083.                 {
  1084.                     falling = TRUE;
  1085.                     while( *ptr > ZERO_LEVEL )
  1086.                     {
  1087.                         write_wav( (char *)ptr, 1 );
  1088.                         bytes++;
  1089.                         ptr++;
  1090.                         if( --table_len == 0 )
  1091.                             break;
  1092.                     }
  1093.                 }
  1094.                 else
  1095.                 {
  1096.                     falling = FALSE;
  1097.                     while( *ptr < ZERO_LEVEL )
  1098.                     {
  1099.                         write_wav( (char *)ptr, 1 );
  1100.                         bytes++;
  1101.                         ptr++;
  1102.                         if( --table_len == 0 )
  1103.                             break;
  1104.                     }
  1105.                 }
  1106.  
  1107. /*
  1108. **  At this point, we finished the last half period of the previous
  1109. **  tone.  Now switch tone.  Make sure we are going in the same direction
  1110. **  as the previous tone, either falling or rising.
  1111. **  This means that if we need to be falling, we must move ahead until
  1112. **  we are.  The tables start out rising.
  1113. */
  1114.                 if( bitvalue == FSK_MARK )
  1115.                 {
  1116.                     ptr = mark;
  1117.                     table_len = MARK_TABLE_LEN;
  1118.                 }
  1119.                 else
  1120.                 {
  1121.                     ptr = space;
  1122.                     table_len = SPACE_TABLE_LEN;
  1123.                 }
  1124.  
  1125. /*
  1126. **  If falling, search for the zero crossing in the other table.
  1127. */
  1128.                 if( falling )
  1129.                 {
  1130.                     ptr++;
  1131.                     table_len--;
  1132.                     for( ; table_len; ptr++, table_len-- )
  1133.                     {
  1134.                         if( *ptr <= ZERO_LEVEL )
  1135.                             break;
  1136.                     }
  1137.                 }
  1138.             } /* end else if at start of buffer */
  1139.         } /* end if bit value changed */
  1140.     } /* end if pure tones */
  1141.  
  1142.     else
  1143.  
  1144. /*
  1145. **  If we are writing normal sine waves, change from one sine wave to
  1146. **  the other.  Do so by finding the corresponding value in the other table,
  1147. **  and continue writing data from the other table.
  1148. */
  1149.     if( format_sine )
  1150.     {
  1151.         if( bitvalue != prev_bitvalue )
  1152.         {
  1153.  
  1154. /*
  1155. **  Check for start of buffer.
  1156. */
  1157.             if( ( prev_bitvalue == FSK_MARK ) && ( ptr == mark ) )
  1158.             {
  1159.                 ptr = space;
  1160.                 table_len = SPACE_TABLE_LEN;
  1161.             }
  1162.             else
  1163.             if( ( prev_bitvalue == FSK_SPACE ) && ( ptr == space ) )
  1164.             {
  1165.                 ptr = mark;
  1166.                 table_len = MARK_TABLE_LEN;
  1167.             }
  1168.             else
  1169.  
  1170. /*
  1171. **  Compare the current value to the last value.  If it is smaller, we
  1172. **  are falling.  If it is larger, we are rising.  If it is the same, we
  1173. **  must be at the top or bottom of the sine wave, and we are then moving
  1174. **  away from that.
  1175. */
  1176.             {
  1177.                 last_value = *(ptr - 1);
  1178.  
  1179. #if 0
  1180.  
  1181. /*
  1182. **  If the space value was larger than any value in the mark table,
  1183. **  we will never find the correct value, so limit it to the top value.
  1184. */
  1185.                 if( last_value > 192 )
  1186.                 {
  1187.                     falling = TRUE;
  1188.                     last_value = 192;
  1189.                 }
  1190.                 else
  1191.                 if( last_value < 64 )
  1192.                 {
  1193.                     falling = FALSE;
  1194.                     last_value = 64;
  1195.                 }
  1196.                 else
  1197.  
  1198. #endif
  1199.  
  1200.                 if( last_value > *ptr )
  1201.                 {
  1202.                     falling = TRUE;
  1203.                 }
  1204.                 else
  1205.                 if( last_value < *ptr )
  1206.                 {
  1207.                     falling = FALSE;
  1208.                 }
  1209.                 else
  1210.  
  1211. /*
  1212. **  Values are the same, moving away from top, determine which top.
  1213. */
  1214.                 {
  1215.                     if( *ptr > ZERO_LEVEL )
  1216.                         falling = TRUE;
  1217.                     else
  1218.                         falling = FALSE;
  1219.                 }
  1220.  
  1221. /*
  1222. **  Now that we know whether we are rising or falling, find the value we
  1223. **  wrote last, but this time in the buffer for the other frequency, and
  1224. **  find it either falling or rising, whatever it was we were doing.
  1225. */
  1226.                 if( bitvalue == FSK_MARK )
  1227.                 {
  1228.                     ptr = mark + 1;
  1229.                     table_len = MARK_TABLE_LEN - 1;
  1230.                 }
  1231.                 else
  1232.                 {
  1233.                     ptr = space + 1;
  1234.                     table_len = SPACE_TABLE_LEN - 1;
  1235.                 }
  1236.  
  1237. /*
  1238. **  Search for the value in the other table.
  1239. */
  1240.                 for( ; table_len; ptr++, table_len-- )
  1241.                 {
  1242.                     if( *ptr == last_value )
  1243.                     {
  1244.                         if( falling )
  1245.                         {
  1246.                             ptr++;
  1247.                             table_len--;
  1248.                             if( table_len == 0 )
  1249.                                 break;
  1250.                             if( *ptr < last_value )
  1251.                                 break;
  1252.                         }
  1253.                         else
  1254.                         {
  1255.                             ptr++;
  1256.                             table_len--;
  1257.                             if( table_len == 0 )
  1258.                                 break;
  1259.                             if( *ptr > last_value )
  1260.                                 break;
  1261.                         }
  1262.                     } /* end if matching value found */
  1263.                 } /* end search for matching value and direction */
  1264.             } /* end else if at start of buffer */
  1265.         } /* end if bit value changed */
  1266.     } /* end if sine wave */
  1267.  
  1268.     else
  1269.  
  1270. /*
  1271. **  Nothing left but square waves.  We cannot really make them smooth.
  1272. **  We do make sure that at least the level changes to the opposite,
  1273. **  so that the length of the first period is correct.
  1274. */
  1275.     if( format_square )
  1276.     {
  1277.         if( bitvalue == FSK_MARK )
  1278.         {
  1279.             if( *ptr > ZERO_LEVEL )
  1280.             {
  1281.                 ptr = mark;
  1282.                 table_len = MARK_TABLE_LEN;
  1283.                 while( *ptr > ZERO_LEVEL )
  1284.                 {
  1285.                     ptr++;
  1286.                     table_len--;
  1287.                 }
  1288.             }
  1289.             else
  1290.             {
  1291.                 ptr = mark;
  1292.                 table_len = MARK_TABLE_LEN;
  1293.             }
  1294.         } /* end if mark */
  1295.         else
  1296.         {
  1297.             if( *ptr > ZERO_LEVEL )
  1298.             {
  1299.                 ptr = space;
  1300.                 table_len = SPACE_TABLE_LEN;
  1301.                 while( *ptr > ZERO_LEVEL )
  1302.                 {
  1303.                     ptr++;
  1304.                     table_len--;
  1305.                 }
  1306.             }
  1307.             else
  1308.             {
  1309.                 ptr = space;
  1310.                 table_len = SPACE_TABLE_LEN;
  1311.             }
  1312.         } /* end else if mark */
  1313.     } /* end if square waves */
  1314.  
  1315. /*
  1316. **  We are now pointing to the correct spot in the buffer.
  1317. **  Write the requested number of samples.  Deduct the number of samples
  1318. **  we used to complete the previous tone.
  1319. */
  1320.     if( samples > bytes )
  1321.     {
  1322.         while( samples - bytes > table_len )
  1323.         {
  1324.             write_wav( (char *)ptr, table_len );
  1325.             bytes += table_len;
  1326.  
  1327.             if( bitvalue == FSK_MARK )
  1328.             {
  1329.                 ptr = mark;
  1330.                 table_len = MARK_TABLE_LEN;
  1331.             }
  1332.             else
  1333.             {
  1334.                 ptr = space;
  1335.                 table_len = SPACE_TABLE_LEN;
  1336.             }
  1337.         }
  1338.         write_wav( (char *)ptr, samples - bytes );
  1339.         ptr += ( samples - bytes );
  1340.         table_len -= ( samples - bytes );
  1341.     }
  1342.  
  1343.     prev_bitvalue = bitvalue;
  1344.  
  1345.     if( table_len == 0 )
  1346.     {
  1347.         if( bitvalue == FSK_MARK )
  1348.         {
  1349.             ptr = mark;
  1350.             table_len = MARK_TABLE_LEN;
  1351.         }
  1352.         else
  1353.         {
  1354.             ptr = space;
  1355.             table_len = SPACE_TABLE_LEN;
  1356.         }
  1357.     }
  1358. }
  1359.  
  1360. /*****************************************************************************
  1361. **  NAME:  write_wav_number()
  1362. **
  1363. **  PURPOSE:
  1364. **      Write a number to the wav file.
  1365. **
  1366. **  DESCRIPTION:
  1367. **      This function will write the specified number to the wav file.
  1368. **
  1369. **  INPUT:
  1370. **      - The number to be written.
  1371. **      - The amount of data to be written.
  1372. **
  1373. **  OUTPUT:
  1374. **      The data is written to the wav file.
  1375. **      The function returns nothing.
  1376. **
  1377. */
  1378.  
  1379. static void         write_wav_number( value, buflen )
  1380. uint32 value;                       /* The number to be written         */
  1381. uint32 buflen;                      /* Number of bytes to be written    */
  1382. {
  1383.     number[0] = value;
  1384.     number[1] = value >> 8;
  1385.     number[2] = value >> 16;
  1386.     number[3] = value >> 24;
  1387.     write_wav( (char *)number, buflen );
  1388. }
  1389.  
  1390. /*****************************************************************************
  1391. ==  EXPORTED FUNCTIONS
  1392. *****************************************************************************/
  1393.  
  1394. /*****************************************************************************
  1395. **  NAME:  MAIN()
  1396. **
  1397. **  PURPOSE:
  1398. **      An entry point for testing or running this utility.
  1399. **
  1400. **  DESCRIPTION:
  1401. **      Prompt for the file to open and then go process it.
  1402. **
  1403. **  INPUT:
  1404. **      argc and argv.
  1405. **
  1406. **  OUTPUT:
  1407. **      Returns an int as it should.
  1408. **
  1409. */
  1410. int                 main( argc, argv )
  1411. int                 argc;               /* Command line argument count  */
  1412. char              * argv[];             /* Command line argument ptrs   */
  1413. {
  1414.     ubyte           answer;                 /* Response to yes/no question  */
  1415.     uint32          arg_ndx;                /* Argument number index        */
  1416.     uint32          arg_no;                 /* Argument number              */
  1417.     uint32          byte;                   /* Byte index                   */
  1418.     uint32          wrk_ndx;                /* Work index                   */
  1419.     bool            end_of_str;             /* Null terminator seen?        */
  1420.     ubyte           input_path[PATH_LEN];   /* Input cas file spec          */
  1421.     uint32          len_chunk;              /* Chunck length                */
  1422.     uint32          len_file;               /* File length                  */
  1423.     ubyte           wav_path[PATH_LEN];     /* Output wave file spec        */
  1424.     ubyte           buf[BUF_LEN];           /* Buffer string                */
  1425.     double          rad;                    /* Radians intermediate value   */
  1426. /*  double          rad_mark;               /* Radians intermediate value   */
  1427. /*  double          rad_space;              /* Radians intermediate value   */
  1428.     uint32          stat;                   /* Status from function         */
  1429.     ubyte           proceed;                /* Proceed with conversion      */
  1430.  
  1431. /*
  1432. **  Allocate buffer space for the tone generators.
  1433. */
  1434.     mark = (ubyte *)malloc((unsigned long)MARK_TABLE_LEN * sizeof( ubyte ) );
  1435.     space = (ubyte *)malloc((unsigned long)SPACE_TABLE_LEN * sizeof( ubyte ) );
  1436.  
  1437.     if( !mark || !space )
  1438.     {
  1439.         fprintf( stderr, "\nCannot allocate buffer, insufficient memory.\n" );
  1440.         cleanup();
  1441.         exit( 255 );
  1442.     }
  1443.  
  1444. /*
  1445. **  Process command line arguments.
  1446. **  We do not treat the options switch as an argument.  It may be placed
  1447. **  anywhere on the command line.  So we have to count the arguments ourselves
  1448. **  so that we know what argument we are processing.
  1449. */
  1450.     arg_no = 0;
  1451.     diagnostics = FALSE;
  1452.     test_tape = 0;
  1453.     baudrate = 600;
  1454.     baudrate_fixed = FALSE;
  1455.     leader = 0;
  1456.     irg = 0;
  1457.     mark_tone = FSK_TONE_MARK;
  1458.     space_tone = FSK_TONE_SPACE;
  1459.     table_len = MARK_TABLE_LEN;
  1460.     recno = 0;
  1461.     format_pure = FALSE;
  1462.     format_sine = TRUE;
  1463.     format_square = FALSE;
  1464.     zero_transition = FALSE;
  1465.  
  1466.     for( arg_ndx = 1; arg_ndx < argc; arg_ndx++ )
  1467.     {
  1468.  
  1469. /*
  1470. **  If we encounter the options switch, process the options.
  1471. **  The options must start with a slash.
  1472. */
  1473.         if( argv[arg_ndx][0] == '/' )
  1474.         {
  1475.  
  1476.             for( wrk_ndx = 1; argv[arg_ndx][wrk_ndx]; wrk_ndx++ )
  1477.             {
  1478.  
  1479. /*
  1480. **  If the user is confused, seeking help, she/he should read the * manual.
  1481. **  We can give them a hint though.
  1482. */
  1483.                 if( argv[arg_ndx][wrk_ndx] == '?' )
  1484.                 {
  1485.                     usage( argv[0] );
  1486.                     exit( 0 );
  1487.                 }
  1488.  
  1489. /*
  1490. **  The /d option selects the diagnostics output.
  1491. */
  1492.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'D' )
  1493.                 {
  1494.                     diagnostics = TRUE;
  1495.                     break;
  1496.                 }
  1497.  
  1498. /*
  1499. **  The /z option selects the transition at the zero level.
  1500. */
  1501.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'Z' )
  1502.                 {
  1503.                     zero_transition = TRUE;
  1504.                     break;
  1505.                 }
  1506.  
  1507. /*
  1508. **  The /w option selects the wave format.
  1509. */
  1510.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'W' )
  1511.                 {
  1512.                     while( argv[arg_ndx][++wrk_ndx] )
  1513.                     {
  1514.                         if( toupper( argv[arg_ndx][wrk_ndx] ) == 'S' )
  1515.                         {
  1516.                             format_pure = FALSE;
  1517.                             format_sine = TRUE;
  1518.                             format_square = FALSE;
  1519.                         }
  1520.                         if( toupper( argv[arg_ndx][wrk_ndx] ) == 'B' )
  1521.                         {
  1522.                             format_pure = FALSE;
  1523.                             format_sine = FALSE;
  1524.                             format_square = TRUE;
  1525.                         }
  1526.                         if( toupper( argv[arg_ndx][wrk_ndx] ) == 'P' )
  1527.                         {
  1528.                             format_pure = TRUE;
  1529.                             format_sine = TRUE;
  1530.                             format_square = FALSE;
  1531.                         }
  1532.                     }
  1533.                     break;
  1534.                 }
  1535.  
  1536. /*
  1537. **  The /t option selects a test tape output.
  1538. */
  1539.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'T' )
  1540.                 {
  1541.                     test_tape = 0;
  1542.                     while( argv[arg_ndx][++wrk_ndx] )
  1543.                     {
  1544.                         if( ( argv[arg_ndx][wrk_ndx] >= '0' ) &&
  1545.                             ( argv[arg_ndx][wrk_ndx] <= '9' ) )
  1546.                         {
  1547.                             test_tape *= 10;
  1548.                             test_tape += argv[arg_ndx][wrk_ndx] - '0';
  1549.                         }
  1550.                     }
  1551.                     break;
  1552.                 }
  1553.  
  1554. /*
  1555. **  The /m option selects the mark tone frequency.
  1556. **  The format of this switch is /m=nnnn where nnnn is a numeric value
  1557. **  that should be around 5327 Hertz.  We accept any number the user enters
  1558. **  though.
  1559. */
  1560.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'M' )
  1561.                 {
  1562.                     mark_tone = 0;
  1563.                     while( argv[arg_ndx][++wrk_ndx] )
  1564.                     {
  1565.                         if( ( argv[arg_ndx][wrk_ndx] >= '0' ) &&
  1566.                             ( argv[arg_ndx][wrk_ndx] <= '9' ) )
  1567.                         {
  1568.                             mark_tone *= 10;
  1569.                             mark_tone += argv[arg_ndx][wrk_ndx] - '0';
  1570.                         }
  1571.                     }
  1572.                     break;
  1573.                 }
  1574.  
  1575. /*
  1576. **  The /s option selects the space tone frequency.
  1577. **  The format of this switch is /s=nnnn where nnnn is a numeric value
  1578. **  that should be around 3995 Hertz.  We accept any number the user enters
  1579. **  though.
  1580. */
  1581.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'S' )
  1582.                 {
  1583.                     space_tone = 0;
  1584.                     while( argv[arg_ndx][++wrk_ndx] )
  1585.                     {
  1586.                         if( ( argv[arg_ndx][wrk_ndx] >= '0' ) &&
  1587.                             ( argv[arg_ndx][wrk_ndx] <= '9' ) )
  1588.                         {
  1589.                             space_tone *= 10;
  1590.                             space_tone += argv[arg_ndx][wrk_ndx] - '0';
  1591.                         }
  1592.                     }
  1593.                     break;
  1594.                 }
  1595.  
  1596. /*
  1597. **  The /b option selects the baudrate.
  1598. **  The format of this switch is /b=nnnn where nnnn is a numeric value
  1599. **  that should be around 600 baud.  We accept any number the user enters
  1600. **  though.
  1601. */
  1602.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'B' )
  1603.                 {
  1604.                     baudrate = 0;
  1605.                     baudrate_fixed = TRUE;
  1606.                     while( argv[arg_ndx][++wrk_ndx] )
  1607.                     {
  1608.                         if( ( argv[arg_ndx][wrk_ndx] >= '0' ) &&
  1609.                             ( argv[arg_ndx][wrk_ndx] <= '9' ) )
  1610.                         {
  1611.                             baudrate *= 10;
  1612.                             baudrate += argv[arg_ndx][wrk_ndx] - '0';
  1613.                         }
  1614.                     }
  1615.                     break;
  1616.                 }
  1617.  
  1618. /*
  1619. **  The /l option selects the length of the leader.
  1620. **  The format of this switch is /l=nnnn where nnnn is a numeric value
  1621. **  that should be around 20000 milli-seconds.  We accept any number the user
  1622. **  enters though.
  1623. */
  1624.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'L' )
  1625.                 {
  1626.                     leader = 0;
  1627.                     while( argv[arg_ndx][++wrk_ndx] )
  1628.                     {
  1629.                         if( ( argv[arg_ndx][wrk_ndx] >= '0' ) &&
  1630.                             ( argv[arg_ndx][wrk_ndx] <= '9' ) )
  1631.                         {
  1632.                             leader *= 10;
  1633.                             leader += argv[arg_ndx][wrk_ndx] - '0';
  1634.                         }
  1635.                     }
  1636.                     break;
  1637.                 }
  1638.  
  1639. /*
  1640. **  The /i option selects the length of inter record gaps.
  1641. **  The format of this switch is /i=nnnn where nnnn is a numeric value
  1642. **  that should be around 250 milli-seconds.  We accept any number the user
  1643. **  enters though.
  1644. */
  1645.                 if( toupper( argv[arg_ndx][wrk_ndx] ) == 'I' )
  1646.                 {
  1647.                     irg = 0;
  1648.                     while( argv[arg_ndx][++wrk_ndx] )
  1649.                     {
  1650.                         if( ( argv[arg_ndx][wrk_ndx] >= '0' ) &&
  1651.                             ( argv[arg_ndx][wrk_ndx] <= '9' ) )
  1652.                         {
  1653.                             irg *= 10;
  1654.                             irg += argv[arg_ndx][wrk_ndx] - '0';
  1655.                         }
  1656.                     }
  1657.                     break;
  1658.                 }
  1659.  
  1660. /*
  1661. **  Ignore other options.
  1662. */
  1663.                 fprintf(stderr,"\nOption %c invalid.\n", argv[arg_ndx][wrk_ndx] );
  1664.                 break;
  1665.             } /* end for all characters after options switch */
  1666.  
  1667. /*
  1668. **  No further processing for the options switches.
  1669. */
  1670.             continue;
  1671.         } /* end if options switch */
  1672.         arg_no++;
  1673.  
  1674. /*
  1675. **  First argument is the file spec.
  1676. */
  1677.         if( arg_no == 1 )
  1678.         {
  1679.             for ( wrk_ndx = 0, end_of_str = FALSE;
  1680.                 wrk_ndx < PATH_LEN; wrk_ndx++ )
  1681.             {
  1682.                 if ( argv[arg_ndx][wrk_ndx] == '\0' ) /* End of argument string?            */
  1683.                     end_of_str = TRUE;
  1684.                 if ( end_of_str )
  1685.                     input_path[wrk_ndx] = '\0';
  1686.                 else
  1687.                     input_path[wrk_ndx] = toupper( argv[arg_ndx][wrk_ndx] );
  1688.             }
  1689.  
  1690.             cas_file = fopen( (char *)input_path, "rb" );
  1691.             if( cas_file == NULL )
  1692.             {
  1693.                 fprintf(stderr, "Cannot open cassette image file %s\n", input_path);
  1694.                 exit( 255 );
  1695.             }
  1696.         }
  1697.     } /* end for all command line arguments */
  1698.  
  1699. /*
  1700. **  If there is no filename on the command line, ask for it.
  1701. */
  1702.     if( arg_no == 0 && !test_tape )
  1703.     {
  1704.  
  1705. /*
  1706. **  Open hailing frequencies.
  1707. **  No command line arguments, so ask what it is we have to do.
  1708. */
  1709.         printf( "Classic Atari cassette tape recovery version April 26, 1999\n" );
  1710.         printf( "Copyright 1998, 1999 by Ernest R. Schreurs. All rights reserved.\n" );
  1711.         printf( "Amiga port by Wojciech Pasiecznik (voydial@wp.pl).\n" );
  1712.  
  1713.  
  1714.         while( TRUE )                       /* until terminated by control C*/
  1715.         {
  1716.             printf( "\nEnter ^C or hit Control C to terminate\n" );
  1717.  
  1718.             do                              /* until .cas file entered    */
  1719.             {
  1720.                 printf("\nEnter .cas file to be converted : ");
  1721.                 GET_BUF();
  1722.  
  1723.                 for ( wrk_ndx = 0, end_of_str = FALSE;
  1724.                     wrk_ndx < PATH_LEN; wrk_ndx++ )
  1725.                 {
  1726.                     if ( wrk_ndx < BUF_LEN )
  1727.                     {
  1728.                         if ( buf[wrk_ndx] == '\n' ) /* End of inputted string?      */
  1729.                             end_of_str = TRUE;
  1730.                         if ( buf[wrk_ndx] == '\0' ) /* Overkill, End marked by \n   */
  1731.                             end_of_str = TRUE;
  1732.                         if ( end_of_str )
  1733.                             input_path[wrk_ndx] = '\0';
  1734.                         else
  1735.                             input_path[wrk_ndx] = toupper( buf[wrk_ndx] );
  1736.                     }
  1737.                 }
  1738.             } while ( input_path[0] == ' ' );
  1739.  
  1740.             do                              /* until answer is Y or N       */
  1741.             {
  1742.                 printf("\nConvert file %s\n", input_path);
  1743.                 printf("\nIs this correct [Y]es or N)o : ");
  1744.                 GET_BUF();
  1745.                 proceed = toupper( buf[0] );
  1746.  
  1747. /*
  1748. **  If blank, default is correct
  1749. */
  1750.                 if ( proceed == '\n' )
  1751.                     proceed = 'Y';
  1752.  
  1753.             } while ( proceed != 'Y' && proceed != 'N' );
  1754.  
  1755.             if ( proceed == 'N' )
  1756.                 continue;
  1757.  
  1758.             cas_file = fopen( (char *)input_path, "rb" );
  1759.             if( cas_file == NULL )
  1760.             {
  1761.                 fprintf(stderr, "Cannot open cassette image file\n");
  1762.                 continue;
  1763.             }
  1764.             break;
  1765.         } /* end while need a valid filename */
  1766.  
  1767.         do                              /* until answer is Y or N       */
  1768.         {
  1769.             printf("\nPrint diagnostic data [Y]es or N)o : ");
  1770.             GET_BUF();
  1771.             answer = toupper( buf[0] );
  1772.  
  1773. /*
  1774. **  If blank, default is correct
  1775. */
  1776.             if ( answer == '\n' )
  1777.                 answer = 'Y';
  1778.         } while ( answer != 'Y' && answer != 'N' );
  1779.  
  1780.         diagnostics = ( answer == 'Y' ) ? TRUE : FALSE;
  1781.  
  1782. /*
  1783. **  Ask for the wave format.
  1784. */
  1785.         format_pure = FALSE;
  1786.         format_sine = FALSE;
  1787.         format_square = FALSE;
  1788.         do                              /* until answer is S or B or P */
  1789.         {
  1790.             printf("\nDo you want s)ine waves, b)lock waves or p)ure waves? [s]: ");
  1791.             GET_BUF();
  1792.             answer = toupper( buf[0] );
  1793.  
  1794. /*
  1795. **  If blank, default is block waves
  1796. */
  1797.             if ( answer == '\n' )
  1798.                 answer = 'S';
  1799.  
  1800.         } while ( (answer != 'S') && (answer != 'B') && (answer != 'P') );
  1801.  
  1802.         if( answer == 'S' )
  1803.         {
  1804.             format_pure = FALSE;
  1805.             format_sine = TRUE;
  1806.             format_square = FALSE;
  1807.         }
  1808.         if( answer == 'B' )
  1809.         {
  1810.             format_pure = FALSE;
  1811.             format_sine = FALSE;
  1812.             format_square = TRUE;
  1813.         }
  1814.         if( answer == 'P' )
  1815.         {
  1816.             format_pure = TRUE;
  1817.             format_sine = TRUE;
  1818.             format_square = FALSE;
  1819.         }
  1820.  
  1821.         do                              /* until answer is Y or N       */
  1822.         {
  1823.             printf("\nUse space/mark transition at zero level Y)es or [N]o : ");
  1824.             GET_BUF();
  1825.             answer = toupper( buf[0] );
  1826.  
  1827. /*
  1828. **  If blank, default is no
  1829. */
  1830.             if ( answer == '\n' )
  1831.                 answer = 'N';
  1832.  
  1833.         } while ( answer != 'Y' && answer != 'N' );
  1834.  
  1835.         zero_transition = ( answer == 'Y' ) ? TRUE : FALSE;
  1836.  
  1837. /*
  1838. **  Ask for the mark tone frequency.
  1839. */
  1840.         printf("\nEnter mark frequency [5327]: ");
  1841.         GET_BUF();
  1842.         mark_tone = 0;
  1843.  
  1844.         for( wrk_ndx = 0; wrk_ndx < BUF_LEN; wrk_ndx++ )
  1845.         {
  1846.             if ( buf[wrk_ndx] == '\n' ) /* End of inputted string?      */
  1847.                 break;
  1848.             if ( buf[wrk_ndx] == '\0' ) /* Overkill, End marked by \n   */
  1849.                 break;
  1850.             if( ( buf[wrk_ndx] >= '0' ) &&
  1851.                 ( buf[wrk_ndx] <= '9' ) )
  1852.             {
  1853.                 mark_tone *= 10;
  1854.                 mark_tone += buf[wrk_ndx] - '0';
  1855.             }
  1856.         }
  1857.         if( mark_tone == 0 )
  1858.             mark_tone = FSK_TONE_MARK;
  1859.  
  1860. /*
  1861. **  Ask for the space tone frequency.
  1862. */
  1863.         printf("\nEnter space frequency [3995]: ");
  1864.         GET_BUF();
  1865.         space_tone = 0;
  1866.  
  1867.         for( wrk_ndx = 0; wrk_ndx < BUF_LEN; wrk_ndx++ )
  1868.         {
  1869.             if ( buf[wrk_ndx] == '\n' ) /* End of inputted string?      */
  1870.                 break;
  1871.             if ( buf[wrk_ndx] == '\0' ) /* Overkill, End marked by \n   */
  1872.                 break;
  1873.             if( ( buf[wrk_ndx] >= '0' ) &&
  1874.                 ( buf[wrk_ndx] <= '9' ) )
  1875.             {
  1876.                 space_tone *= 10;
  1877.                 space_tone += buf[wrk_ndx] - '0';
  1878.             }
  1879.         }
  1880.         if( space_tone == 0 )
  1881.             space_tone = FSK_TONE_SPACE;
  1882.  
  1883. /*
  1884. **  Ask for a fixed baudrate.
  1885. */
  1886.         printf("\nEnter fixed baudrate if desired 425 - 875 : ");
  1887.         GET_BUF();
  1888.         baudrate = 0;
  1889.  
  1890.         for( wrk_ndx = 0; wrk_ndx < BUF_LEN; wrk_ndx++ )
  1891.         {
  1892.             if ( buf[wrk_ndx] == '\n' ) /* End of inputted string?      */
  1893.                 break;
  1894.             if ( buf[wrk_ndx] == '\0' ) /* Overkill, End marked by \n   */
  1895.                 break;
  1896.             if( ( buf[wrk_ndx] >= '0' ) &&
  1897.                 ( buf[wrk_ndx] <= '9' ) )
  1898.             {
  1899.                 baudrate *= 10;
  1900.                 baudrate += buf[wrk_ndx] - '0';
  1901.             }
  1902.         }
  1903.         if( baudrate == 0 )
  1904.             baudrate = 600;
  1905.         else
  1906.             baudrate_fixed = TRUE;
  1907.  
  1908. /*
  1909. **  Ask for the fixed length of the leader.
  1910. */
  1911.         printf("\nLength of leader if fixed length in milli-seconds : ");
  1912.         GET_BUF();
  1913.         leader = 0;
  1914.  
  1915.         for( wrk_ndx = 0; wrk_ndx < BUF_LEN; wrk_ndx++ )
  1916.         {
  1917.             if ( buf[wrk_ndx] == '\n' ) /* End of inputted string?      */
  1918.                 break;
  1919.             if ( buf[wrk_ndx] == '\0' ) /* Overkill, End marked by \n   */
  1920.                 break;
  1921.             if( ( buf[wrk_ndx] >= '0' ) &&
  1922.                 ( buf[wrk_ndx] <= '9' ) )
  1923.             {
  1924.                 leader *= 10;
  1925.                 leader += buf[wrk_ndx] - '0';
  1926.             }
  1927.         }
  1928.  
  1929. /*
  1930. **  Ask for the fixed length of the irg.
  1931. */
  1932.         printf("\nLength of Inter Record Gap if fixed length in milli-seconds : ");
  1933.         GET_BUF();
  1934.         irg = 0;
  1935.  
  1936.         for( wrk_ndx = 0; wrk_ndx < BUF_LEN; wrk_ndx++ )
  1937.         {
  1938.             if ( buf[wrk_ndx] == '\n' ) /* End of inputted string?      */
  1939.                 break;
  1940.             if ( buf[wrk_ndx] == '\0' ) /* Overkill, End marked by \n   */
  1941.                 break;
  1942.             if( ( buf[wrk_ndx] >= '0' ) &&
  1943.                 ( buf[wrk_ndx] <= '9' ) )
  1944.             {
  1945.                 irg *= 10;
  1946.                 irg += buf[wrk_ndx] - '0';
  1947.             }
  1948.         }
  1949.  
  1950.     } /* end else if command line arguments */
  1951.  
  1952. /*
  1953. **  Compute the sine value for all sample positions.
  1954. **  The mark tone is 5327 Hertz.  One period is 2 PI radians,
  1955. **  One second contains 5327 periods.  We have 44,100 samples in one second.
  1956. **  To evenly divide these 5327 * 2 PI radians over 44,100 samples, we
  1957. **  have to divide by 44,100.  To get the radians value, multiply by the
  1958. **  sample position number.  Similar computations are done for the space tone.
  1959. **  Convert the sine value to a PCM value with proper audio volume by
  1960. **  multiplying it by 64.
  1961. **  The center of the PCM values is at 128, thus we add 128.
  1962. */
  1963.     rad = (double)mark_tone * 2.0 * PI / MARK_TABLE_LEN;
  1964.     for( byte = 0; byte < MARK_TABLE_LEN; byte++ )
  1965.     {
  1966.         mark[byte] = sin( rad * byte ) * 64 + ZERO_LEVEL;
  1967.  
  1968.         if( format_square )
  1969.         {
  1970.             if( mark[byte] >= ZERO_LEVEL )
  1971.                 mark[byte] = 192;
  1972.             else
  1973.                 mark[byte] = 64;
  1974.         }
  1975.  
  1976.     }
  1977.     rad = (double)space_tone * 2.0 * PI / SPACE_TABLE_LEN;
  1978.     for( byte = 0; byte < SPACE_TABLE_LEN; byte++ )
  1979.     {
  1980.         space[byte] = sin( rad * byte ) * 64 + ZERO_LEVEL;
  1981.  
  1982.         if( format_square )
  1983.         {
  1984.             if( space[byte] >= ZERO_LEVEL )
  1985.                 space[byte] = 128;
  1986.             else
  1987.                 space[byte] = 64;
  1988.         }
  1989.  
  1990.     }
  1991.  
  1992. /*
  1993. **  Initialize the pointer to the table.
  1994. */
  1995.     bytelen = ( 44100L * 10 ) / baudrate;
  1996.     bitlen = 44100L / baudrate;
  1997.  
  1998. #if 0
  1999.  
  2000.     bit_stretch = 9;
  2001.     if( zero_transition && format_square )
  2002.         bit_stretch = 0;
  2003.  
  2004. #endif
  2005.  
  2006.     header_written = FALSE;
  2007.     prev_bitvalue = FSK_MARK;
  2008.     ptr = mark;
  2009.     table_len = MARK_TABLE_LEN;
  2010.  
  2011. /*
  2012. **  If we must write a test-tape, do so, and then quit.
  2013. */
  2014.     if( test_tape )
  2015.     {
  2016.         write_test_tape();
  2017.     } /* end if test tape */
  2018.     else
  2019.  
  2020. /*
  2021. **  Generate a wave file based on the .cas file.
  2022. */
  2023.     {
  2024.  
  2025. /*
  2026. **  Process the header of the .cas file.
  2027. */
  2028.         stat = process_header();
  2029.         if( stat == FAILURE )
  2030.         {
  2031.             cleanup();
  2032.             exit( 255 );
  2033.         }
  2034.  
  2035.         PRINT( ("File : %s\n", input_path ) );
  2036.  
  2037.         memcpy( wav_path, input_path, PATH_LEN );
  2038.  
  2039. /*
  2040. **  Find the dot and replace by or add .wav extension.
  2041. */
  2042.         wrk_ndx = STRLEN(wav_path);
  2043.         for( ;; )
  2044.         {
  2045.             if( wav_path[wrk_ndx] == '.' )
  2046.             {
  2047.                 memcpy( &(wav_path[wrk_ndx]), ".wav", 5 );
  2048.                 break;
  2049.             }
  2050.             if( ( wrk_ndx == 0 ) ||
  2051.                 ( wav_path[wrk_ndx] == '/' ) ||
  2052.                 ( wav_path[wrk_ndx] == '\\' ) )
  2053.             {
  2054.                 memcpy( &(wav_path[STRLEN(wav_path)]), ".wav", 5 );
  2055.                 break;
  2056.             }
  2057.             wrk_ndx--;
  2058.         }
  2059.  
  2060.         wav_file = fopen( (char *)wav_path, "wb" );
  2061.         if( wav_file == NULL )
  2062.         {
  2063.             fprintf(stderr, "\nCannot open .wav file!\n");
  2064.             cleanup();
  2065.             exit( 255 );
  2066.         }
  2067.  
  2068.         fprintf(stderr, "\nProcessing, please wait!\n");
  2069.  
  2070. /*
  2071. **  Read records, and process them.
  2072. */
  2073.  
  2074.         while( read_record() == SUCCESS )
  2075.             process_record();
  2076.  
  2077.     } /* end else if a test tape */
  2078.  
  2079. /*
  2080. **  Fix up the file size and the chunk size in the wave file.
  2081. **  Compute the lengths.  Write an alignment byte if needed.
  2082. **  Position the file at the chunk size and update it and do the
  2083. **  same for the file size.
  2084. */
  2085.     len_chunk = pos - pos_chunk_size - 4;
  2086.     len_file  = pos - pos_file_size - 4;
  2087.     if( len_chunk & 0x01L )
  2088.         write_wav( (char *)"\0", (uint32)1L );     /* Write alignment byte */
  2089.     fseek( wav_file, pos_chunk_size, SEEK_SET );   /* Go back to chunk size */
  2090.     write_wav_number( len_chunk, (uint32)4L );
  2091.     fseek( wav_file, pos_file_size, SEEK_SET );    /* Go back to file size */
  2092.     write_wav_number( len_file, (uint32)4L );
  2093.  
  2094.     cleanup();
  2095.     return 0;
  2096. }
  2097.  
  2098. /*****************************************************************************
  2099. **  MODIFICATION HISTORY
  2100. **
  2101. **  DATE        BY   Description
  2102. **  ----------  ---  ---------------------------------------------------------
  2103. **  1998/12/30  ERS  Project start
  2104. **  1999/04/26  ERS  Release 01.00
  2105. **
  2106. *****************************************************************************/
  2107.